package com.horay.statemachiedemo.multi.builder;

import com.horay.statemachiedemo.multi.action.ComplexChoiceFailureAction;
import com.horay.statemachiedemo.multi.action.ComplexChoiceSuccessAction;
import com.horay.statemachiedemo.multi.constant.StateMachineConstant;
import com.horay.statemachiedemo.multi.enums.ComplexState;
import com.horay.statemachiedemo.multi.event.ComplexEvent;
import com.horay.statemachiedemo.multi.guard.ComplexCheckChoiceGuard;
import com.horay.statemachiedemo.multi.guard.ComplexDealChoiceGuard;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.config.StateMachineBuilder;
import org.springframework.statemachine.listener.StateMachineListener;
import org.springframework.statemachine.listener.StateMachineListenerAdapter;
import org.springframework.statemachine.transition.Transition;

import java.util.EnumSet;

/**
 * Class description
 *
 * @author heyingcheng
 * @date 2020/10/23
 */
@Slf4j
@Configuration
public class ComplexStateMachineBuilder {

    /**
     * 构建状态机
     *
     * @param beanFactory
     * @return
     * @throws Exception
     */
    public StateMachine<ComplexState, ComplexEvent> build(BeanFactory beanFactory) throws Exception {
        StateMachineBuilder.Builder<ComplexState, ComplexEvent> builder = StateMachineBuilder.builder();

        log.info("构建复杂状态机");

        builder.configureConfiguration()
                .withConfiguration()
                .machineId(StateMachineConstant.COMPLEX_MACHINE_ID)
                .beanFactory(beanFactory)
                .listener(complexListener());

        builder.configureStates()
                .withStates()
                .initial(ComplexState.BLANK_FORM)
                .choice(ComplexState.CHECK_CHOICE)
                .choice(ComplexState.DEAL_CHOICE)
                .states(EnumSet.allOf(ComplexState.class));

        builder.configureTransitions()
                .withExternal().source(ComplexState.BLANK_FORM).target(ComplexState.FULL_FORM).event(ComplexEvent.WRITE)
                .and()
                .withExternal().source(ComplexState.FULL_FORM).target(ComplexState.CHECK_CHOICE).event(ComplexEvent.CHECK)
                .and()
                .withChoice().source(ComplexState.CHECK_CHOICE).first(ComplexState.CONFIRM_FORM, new ComplexCheckChoiceGuard(), new ComplexChoiceSuccessAction()).last(ComplexState.DEAL_FORM, new ComplexChoiceFailureAction())
                .and()
                .withExternal().source(ComplexState.CONFIRM_FORM).target(ComplexState.SUCCESS_FORM).event(ComplexEvent.SUBMIT)
                .and()
                .withExternal().source(ComplexState.DEAL_FORM).target(ComplexState.DEAL_CHOICE).event(ComplexEvent.DEAL)
                .and()
                .withChoice().source(ComplexState.DEAL_CHOICE).first(ComplexState.FULL_FORM, new ComplexDealChoiceGuard()).last(ComplexState.FAILED_FORM);
        return builder.build();
    }

    @Bean
    public StateMachineListener<ComplexState, ComplexEvent> complexListener() {
        return new StateMachineListenerAdapter<ComplexState, ComplexEvent>() {

            @Override
            public void transition(Transition<ComplexState, ComplexEvent> transition) {
                if (transition.getTarget().getId() == ComplexState.BLANK_FORM) {
                    log.info("Listener:空白表单，待填写");
                    return;
                }

                if (transition.getSource().getId() == ComplexState.BLANK_FORM
                        && transition.getTarget().getId() == ComplexState.FULL_FORM) {
                    log.info("Listener:用户填写表单，待验证");
                    return;
                }

                if (transition.getSource().getId() == ComplexState.FULL_FORM
                        && transition.getTarget().getId() == ComplexState.CONFIRM_FORM) {
                    log.info("Listener:用户验证表单，待提交");
                    return;
                }

                if (transition.getSource().getId() == ComplexState.CONFIRM_FORM
                        && transition.getTarget().getId() == ComplexState.SUCCESS_FORM) {
                    log.info("Listener:用户已提交，表单完成");
                    return;
                }
            }

        };
    }

}
